﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using Google.Protobuf;
using Cemit.PolyProto;

namespace Cemit.PolyServer
{
    [System.Obsolete("使用Cemit.PolyServer.Lobby命名空间下的LobbyServer")]
    class LobbyServer : PolyServer
    {
        const short MAX_Match_FULL_NUMBER = 256;

        static Dictionary<short, Queue<Match>> matchesQueues;

        [Obsolete]
        static Dictionary<string, Queue<Match>> modelMatchPairs;
        [Obsolete]
        static Dictionary<string, short> modelFullNumberPairs;

        public LobbyServer()
        {
            InstantiateMatchesQueues();

            //InstantiateDictionaryFromModels();
        }

        /// <summary>
        /// 初始化匹配队列字典
        /// </summary>
        private void InstantiateMatchesQueues()
        {
            matchesQueues = new Dictionary<short, Queue<Match>>();

            for (short i = 1; i <= MAX_Match_FULL_NUMBER; i++)
            {
                matchesQueues.Add(i, new Queue<Match>());
            }
        }

        [Obsolete]
        private void InstantiateMatchesDictionaryFromModels()
        {
            modelMatchPairs = new Dictionary<string, Queue<Match>>();
            modelFullNumberPairs = new Dictionary<string, short>();

            foreach (var item in Jsons.Get("GameModels").GetKeys())
            {
                modelMatchPairs.Add(item, new Queue<Match>() { });
                modelFullNumberPairs.Add(item, GetFullNumber(item));
            }

            short GetFullNumber(string model)
                => short.Parse(Jsons.Get("GameModels").GetValue($"{model}:number"));
        }

        

        /// <summary>
        /// 加入匹配队列
        /// </summary>
        [Obsolete("使用JoinMatch(Player, short)")]
        public void JoinMatch(Player player, string model)
        {
            if (!modelMatchPairs.ContainsKey(model))
            {
                Debug.LogError("加入匹配失败，找不到游戏模式：" + model);
                return;
            }
            
            //从匹配队列中获得一个匹配
            Match match = DequeueMatch(); 

            if (match == null)
            {
                match = new Match(modelFullNumberPairs[model]);
            }

            //添加角色
            match.AddPlayer(player);

            if (match.IsFull)
            {
                //匹配完成
                MatchCompleted(match);
            }
            else
            {
                //重新加入队列
                EnqueueMatch();
            }

            void EnqueueMatch()
            {
                lock (modelMatchPairs[model])
                {
                    modelMatchPairs[model].Enqueue(match);
                }
            }

            Match DequeueMatch()
            {
                lock (modelMatchPairs[model])
                {
                    //新建匹配
                    if (modelMatchPairs[model].TryDequeue(out var ret))
                    {
                        return ret;
                    }
                    else
                    {
                        return null;
                    }
                }
            }
        }

        [Obsolete("TODO: 正确的message")]
        private void MatchCompleted(Match match)
        {
            //Debug.Log("匹配已完成！");
            ////向所有玩家发送匹配完成
            //IMessage message = new Msg_Lobby_JoinMatchSuccess
            //{
            //};
            //foreach (var item in match.Players)
            //{
            //    item.Send(message);
            //}
        }

        class Match
        {
            public bool IsFull => m_Players.Count == m_FullNumber;
            public IEnumerable<Player> Players => m_Players;

            readonly short m_FullNumber;
            readonly List<Player> m_Players = new List<Player>();

            public Match(short fullNumber)
            {
                m_FullNumber = fullNumber;
            }

            public Match AddPlayer(Player player)
            {
                m_Players.Add(player);
                return this;
            }

            public Match RemovePlayer(Player player)
            {
                m_Players.Remove(player);
                return this;
            }
        }
    }
}
